package repositories

import (
	"context"
	"reflect"
)

// --- 基础职责接口 ---

// Creator 定义实体创建相关操作
// Create 负责将新实体持久化到底层存储
type Creator[T any] interface {
	// Create 将实体写入存储层，返回执行过程中的错误
	Create(ctx context.Context, entity *T) error
}

// Updater 定义实体更新相关操作
// Update 根据主键更新指定字段，避免零值覆盖
type Updater[T any] interface {
	// Update 按主键更新指定字段
	Update(ctx context.Context, id uint, fields map[string]interface{}) error
}

// Deleter 定义实体删除相关操作
// Delete 为软删除；ForceDelete 为物理删除
type Deleter[T any] interface {
	// Delete 执行软删除（若实体支持）
	Delete(ctx context.Context, id uint) error
	// ForceDelete 无视软删除，强制物理删除
	ForceDelete(ctx context.Context, id uint) error
}

// Reader 定义实体读取相关操作
// GetByID/GetAll 获取单条或全量数据
// GetByCondition/GetOneByCondition 结合 QueryOptions 进行条件查询
type Reader[T any] interface {
	// GetByID 根据主键获取实体
	GetByID(ctx context.Context, id uint) (*T, error)
	// GetAll 获取所有实体记录
	GetAll(ctx context.Context) ([]*T, error)
	// GetByCondition 按条件批量查询实体
	GetByCondition(ctx context.Context, options *QueryOptions) ([]*T, error)
	// GetOneByCondition 按条件查询单个实体
	GetOneByCondition(ctx context.Context, options *QueryOptions) (*T, error)
}

// Paginator 定义基于页码的分页查询
type Paginator[T any] interface {
	// GetWithPagination 返回分页数据及总量
	GetWithPagination(ctx context.Context, page, pageSize int, options *QueryOptions) ([]*T, int64, error)
}

// BatchOperator 定义批量操作
type BatchOperator[T any] interface {
	// CreateBatch 批量创建实体
	CreateBatch(ctx context.Context, entities []*T) error
	// UpdateBatch 针对不同实体批量更新指定字段
	UpdateBatch(ctx context.Context, items map[uint]map[string]interface{}) error
	// UpdateFieldsBatch 针对实体集合批量更新相同字段
	UpdateFieldsBatch(ctx context.Context, ids []uint, fields map[string]interface{}) error
	// DeleteBatch 批量执行软删除
	DeleteBatch(ctx context.Context, ids []uint) error
	// ForceDeleteBatch 批量执行物理删除
	ForceDeleteBatch(ctx context.Context, ids []uint) error
}

// SoftDeleteRestorer 定义软删除数据的查询与恢复
type SoftDeleteRestorer[T any] interface {
	// GetWithDeleted 获取包含软删除数据的列表
	GetWithDeleted(ctx context.Context) ([]*T, error)
	// GetDeletedOnly 获取仅软删除的数据
	GetDeletedOnly(ctx context.Context) ([]*T, error)
	// Restore 恢复单个软删除数据
	Restore(ctx context.Context, id uint) error
	// RestoreBatch 批量恢复软删除数据
	RestoreBatch(ctx context.Context, ids []uint) error
}

// Counter 定义计数与存在性判断
type Counter[T any] interface {
	// Count 统计满足条件的数量
	Count(ctx context.Context, options *QueryOptions) (int64, error)
	// Exists 判断是否存在满足条件的记录
	Exists(ctx context.Context, options *QueryOptions) (bool, error)
	// ExistsById 判断指定主键是否存在
	ExistsById(ctx context.Context, id uint) (bool, error)
}

// Transactional 定义事务相关操作
type Transactional[T any] interface {
	// WithTx 返回绑定在指定事务上的仓储实例
	WithTx(tx interface{}) BaseRepository[T]
}

// BaseRepository 聚焦最常用的CRUD职责，其余可按需组合
type BaseRepository[T any] interface {
	Creator[T]
	Reader[T]
	Updater[T]
	Deleter[T]
	Transactional[T]
}

// PaginatableRepository 将分页能力与基础仓储组合
type PaginatableRepository[T any] interface {
	BaseRepository[T]
	Paginator[T]
}

// BatchCapableRepository 将批量能力与基础仓储组合
type BatchCapableRepository[T any] interface {
	BaseRepository[T]
	BatchOperator[T]
}

// SoftDeleteCapableRepository 将软删恢复能力与基础仓储组合
type SoftDeleteCapableRepository[T any] interface {
	BaseRepository[T]
	SoftDeleteRestorer[T]
}

// Repository 通用仓储接口
type Repository interface {
	// 示例仓储 - 演示如何添加新的仓储方法
	Example() ExampleRepository

	// 这里可以添加其他业务仓储接口
	// User() UserRepository
	// Article() ArticleRepository
}

// TransactionManager 事务管理器接口
type TransactionManager interface {
	// 开始事务
	Begin(ctx context.Context) (Transaction, error)

	// 在事务中执行操作
	WithTransaction(ctx context.Context, fn func(tx Transaction) error) error
}

// Transaction 事务接口
type Transaction interface {
	// 提交事务
	Commit() error

	// 回滚事务
	Rollback() error

	// 获取仓储实例（在事务中使用）
	Repository() Repository

	// 获取原始事务对象
	Raw() interface{}
}

// QueryOptions 定义仓储查询的通用选项，集中控制过滤、排序、分页等行为
type QueryOptions struct {
	Page int `json:"page"` // 页码，从1开始；0表示未设置，将由调用方决定

	PageSize int `json:"page_size"` // 每页条数；0表示未设置，由仓储或调用方使用默认值

	OrderBy string `json:"order_by"` // 排序字段名，例如"created_at"；支持 GORM 字段格式

	Order string `json:"order"` // 排序方向，可选"asc"或"desc"（大小写不敏感），为空时默认升序

	Fields []string `json:"fields"` // 需要返回的字段列表，留空表示选择全部字段

	Preload []string `json:"preload"` // 需要预加载的关联名称列表，对应 GORM 的 Preload

	Filters map[string]interface{} `json:"filters"` // 等值过滤条件，键为字段名，值为过滤值

	Conditions []QueryCondition `json:"conditions"` // 复杂条件（模糊、范围、集合等）
}

// QueryCondition 定义高级过滤条件
type QueryCondition struct {
	Field    string      `json:"field"`    // 字段名
	Operator string      `json:"operator"` // 操作符：like、between、in、gt、gte、lt、lte 等
	Value    interface{} `json:"value"`    // 主值，like/between/in 等场景使用
	Value2   interface{} `json:"value2"`   // between 上界，其它场景可忽略
}

// Normalize 规范化分页参数，设置默认页码与页大小，并限制最大值
func (o *QueryOptions) Normalize(defaultPage, defaultPageSize, maxPageSize int) {
	if o == nil {
		return
	}

	if defaultPage <= 0 {
		defaultPage = 1
	}
	if defaultPageSize <= 0 {
		defaultPageSize = 50
	}
	if maxPageSize <= 0 {
		maxPageSize = 500
	}

	if o.Page <= 0 {
		o.Page = defaultPage
	}

	if o.PageSize <= 0 {
		o.PageSize = defaultPageSize
	} else if o.PageSize > maxPageSize {
		o.PageSize = maxPageSize
	}
}

// GetEntityType 获取实体类型（用于泛型仓储）
func GetEntityType[T any]() reflect.Type {
	var zero T
	return reflect.TypeOf(zero)
}

// PaginationResult 分页结果
type PaginationResult[T any] struct {
	Data       []*T  `json:"data"`
	Total      int64 `json:"total"`
	Page       int   `json:"page"`
	PageSize   int   `json:"page_size"`
	TotalPages int   `json:"total_pages"`
}

// NewPaginationResult 创建分页结果
func NewPaginationResult[T any](data []*T, total int64, page, pageSize int) *PaginationResult[T] {
	totalPages := int((total + int64(pageSize) - 1) / int64(pageSize))
	return &PaginationResult[T]{
		Data:       data,
		Total:      total,
		Page:       page,
		PageSize:   pageSize,
		TotalPages: totalPages,
	}
}

// 注意：SoftDeleteRepository 已移除
// 现在直接使用 BaseRepository，GORM 会自动处理软删除逻辑
// 对于有 gorm.DeletedAt 字段的实体，Delete() 会自动进行软删除
// 对于需要物理删除的场景，使用 ForceDelete() 方法
